<?php
/** @noinspection PhpUnused */

namespace app\admin\controller\shop\order;

use app\admin\controller\shop\Base;
use app\admin\library\Auth;
use app\admin\model\shop\order\OrderStatusLog;
use app\shop\enums\order\OrderCancelReviewResult;
use app\shop\enums\order\OrderStatus;
use app\shop\library\ShopHelper;
use app\shop\library\ShopLogHelper;
use app\shop\service\LogService;
use app\shop\service\OrderExportService;
use app\shop\service\OrderService;
use ba\Exception;
use think\db\exception\DbException;
use Throwable;

/**
 * 订单管理
 */
class Order extends Base
{
    /**
     * Order模型对象
     * @var object
     * @phpstan-var \app\admin\model\shop\order\Order
     */
    protected object $model;

    protected array|string $preExcludeFields = [];

    protected string|array $quickSearchField = ['id'];

    protected array $noNeedPermission = [];

    protected string $withJoinType = 'left';

    protected array $withJoinTable = [
        'user' => ['nickname', 'openid'],
    ];

    protected string|array $indexField = [];

    public function initialize(): void
    {
        parent::initialize();
        $this->model = new \app\admin\model\shop\order\Order;
    }

    /**
     * 若需重写查看、编辑、删除等方法，请复制 @see \app\admin\library\traits\Backend 中对应的方法至此进行重写
     */

    /**
     * 列表
     * @return void
     * @throws Throwable
     * @throws DbException
     */
    public function index(): void
    {
        if ($this->request->param('select')) {
            $this->select();
        }

        list($where, $alias, $limit, $order) = $this->queryBuilder();

        $query = $this->model
            ->alias($alias)
            ->field($this->indexField)
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->where($where)
            ->with(
                [
                    'detail'     => function ($query) { },
                    'delivery'   => function ($query) {
                        $query->with(['company']);
                    },
                    'status_log' => function ($query) {
                        $query->order('create_time', 'desc');
                    },
                    'address'    => function ($query) { },
                ]
            )
            ->order($order);

        $res = $query->paginate($limit);

        $this->success('', [
            'list'       => $res->items(),
            'total'      => $res->total(),
            'remark'     => get_route_remark(),
            'statusInfo' => $this->statusInfo()
        ]);
    }

    //订单状态信息
    public function statusInfo(): array
    {
        $statusData   = OrderStatus::getData();
        $tipStatusArr = [OrderStatus::TO_SHIPPED, OrderStatus::REFUND];

        $statusCount = $this->model
            ->whereIn('status', $tipStatusArr)
            ->field(['count(*) as count', 'status'])
            ->group('status')
            ->column('count(*) as count', 'status');

        foreach ($statusData as &$value) {
            $value['count'] = $statusCount[$value['value']] ?? 0;
        }

        return $statusData;
    }

    /**
     * 取消订单审核
     * @return void
     */
    public function cancel(): void
    {
        $data        = $this->request->post();
        $auditStatus = $data['status'] ?? '';

        $order = $this->model->where(['id' => $data['id']])->with(['detail'])->findOrEmpty();
        if ($order->isEmpty()) {
            $this->error('订单异常,请刷新');
        }
        if (!in_array($auditStatus, [OrderCancelReviewResult::AGREE, OrderCancelReviewResult::REFUSE])) {
            $this->error('审核状态异常');
        }

        $this->model->startTrans();
        try {
            if ($auditStatus == OrderCancelReviewResult::REFUSE) {
                $cancelRemark = $data['remark'] ?? '拒绝取消';

                $orderStatusLog = OrderStatusLog::where(['order_id' => $order->id])
                    ->order('id', 'desc')
                    ->findOrEmpty();
                // 回滚订单状态
                $order->status        = $orderStatusLog->original_status;
                $order->cancel_remark = $cancelRemark;
                $order->save();
                // 维护订单日志
                $cancelMsg = "后台拒绝取消";
                LogService::orderStatusLog(
                    $order->id,
                    $orderStatusLog->original_status,
                    $cancelMsg,
                    $this->auth->id,
                    true
                );
            }

            if ($auditStatus == OrderCancelReviewResult::AGREE) {
                $cancelRemark = $data['remark'] ?? '同意取消';

                $orderService = new OrderService();
                $orderService->cancelOrder([
                    'order_id'      => $order->id,
                    'cancel_reason' => $order->cancel_reason,
                    'cancel_remark' => $cancelRemark,
                    'operator_id'   => $this->auth->id,
                    'is_admin'      => true,
                ]);
            }

            $this->model->commit();
        } catch (Throwable $e) {
            $this->model->rollback();
            $this->error('审核失败', ['err' => $e->getMessage()]);
        }

        $this->success('审核完成');
    }

    /**
     * 关闭订单
     * @return void
     * @throws \Exception
     */
    public function close(): void
    {
        $params = $this->request->post();

        $order = $this->model->where(['id' => $params['id']])->findOrEmpty();
        if ($order->isEmpty()) {
            $this->error('订单异常,请刷新');
        }
        if ($order->status == OrderStatus::CANCEL) {
            $this->error('当前订单已取消,请刷新');
        }

        try {
            (new OrderService())->cancelOrder([
                'order_id'      => $order->id,
                'cancel_reason' => '后台关闭订单',
                'cancel_remark' => $params['remark'] ?? '',
                'refund_amount' => $order->pay_price,
                'operator_id'   => $this->auth->id,
                'is_admin'      => true,
            ]);
        } catch (Exception $e) {
            ShopLogHelper::error('后台关闭订单异常', ['params' => $params], $e);
            $this->error('订单关闭失败', ['err' => $e->getMessage()]);
        }

        $this->success('订单关闭成功');
    }


    /**
     * 创建订单导出任务
     * @return void
     */
    public function addExportTask(): void
    {
        $params = $this->request->param();

        $this->model->startTrans();
        try {
            // 模型验证
            if ($this->modelValidate) {
                $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                if (class_exists($validate)) {
                    $validate = new $validate;
                    if ($this->modelSceneValidate) $validate->scene('export');
                    $validate->check($params);
                }
            }

            list($where, $alias, $limit, $order) = $this->queryBuilder();

            $startTime = $this->model->order('create_time', 'asc')
                ->limit(1)
                ->value('create_time');

            if (empty($where)) {
                $where[] = ['order.create_time', 'between', [$startTime, time()]];
            } else {
                foreach ($where as $item) {
                    list($field) = $item;
                    if (!in_array($field, ['create_time', 'order.create_time'])) {
                        $where[] = ['order.create_time', 'between', [$startTime, time()]];
                    }
                }
            }

            $exportModel = new \app\admin\model\shop\order\Export();
            $count       = $exportModel->where(['name' => $params['name']])->count();
            if ($count > 0) {
                throw new Exception('导出文件名称已存在');
            }

            $data['query_params']  = ShopHelper::array_to_json([
                'where'         => $where,
                'alias'         => $alias,
                'limit'         => $params['total'],
                'order'         => $order,
                'withJoinTable' => $this->withJoinTable,
                'withJoinType'  => $this->withJoinType,
            ]);
            $data['export_fields'] = ShopHelper::array_to_json($params['export_fields']);
            $data['admin_id']      = Auth::instance()->getAdmin()->id;
            $data['max_row_num']   = $params['export_max_row_num'];
            $data['name']          = $params['name'];

            $exportTask = \app\admin\model\shop\order\Export::create($data);

            (new OrderExportService())->addExportOrderJob($exportTask->id);

            $this->model->commit();
        } catch (Throwable $e) {
            $this->model->rollback();
            $this->error($e->getMessage() ?: __('导出任务创建失败'), ['err' => $e->getMessage()]);
        }

        $this->success(__('导出任务创建成功'));
    }
}